package cn.congine.wizarpos.mall.action;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Random;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import cn.congine.wizarpos.mall.entity.MrtMerchantDef;
import cn.congine.wizarpos.mall.entity.MyOnlineActivity;
import cn.congine.wizarpos.mall.entity.MyOnlineActivityDetail;
import cn.congine.wizarpos.mall.entity.MyOnlineActivityHistory;
import cn.congine.wizarpos.mall.entity.MyOpenidRelation;
import cn.congine.wizarpos.mall.entity.MyRedEnvelopes;
import cn.congine.wizarpos.mall.entity.MyShake;
import cn.congine.wizarpos.mall.entity.SysInToken;
import cn.congine.wizarpos.mall.model.MrtTicketDef;
import cn.congine.wizarpos.mall.model.MrtWechartUserInfo;
import cn.congine.wizarpos.mall.model.dzx.DxChartMemberRegisterInput;
import cn.congine.wizarpos.mall.model.dzx.DxChartMemberRegisterOutput;
import cn.congine.wizarpos.mall.model.dzx.DxChartMemberValidateInput;
import cn.congine.wizarpos.mall.model.dzx.DxChartMemberValidateOutput;
import cn.congine.wizarpos.mall.model.dzx.MemberSyncInput;
import cn.congine.wizarpos.mall.model.dzx.MemberSyncOutput;
import cn.congine.wizarpos.mall.model.dzx.RegisteredMemberQueryInput;
import cn.congine.wizarpos.mall.model.dzx.RegisteredMemberQueryOutput;
import cn.congine.wizarpos.mall.model.dzx.SendCouponsInput;
import cn.congine.wizarpos.mall.model.dzx.SendCouponsOutput;
import cn.congine.wizarpos.mall.model.dzx.WeightCategory;
import cn.congine.wizarpos.mall.model.open.AccessTokenInput;
import cn.congine.wizarpos.mall.model.open.AccessTokenOutput;
import cn.congine.wizarpos.mall.model.open.CommonResultOutput;
import cn.congine.wizarpos.mall.model.open.DzxWxHongbaoSendInput;
import cn.congine.wizarpos.mall.model.open.MerchantDef;
import cn.congine.wizarpos.mall.model.open.MerchantDefQueryInput;
import cn.congine.wizarpos.mall.model.open.MerchantDefQueryOutput;
import cn.congine.wizarpos.mall.model.open.MrtWechartUserInfoInput;
import cn.congine.wizarpos.mall.model.open.MrtWechartUserInfoOutput;
import cn.congine.wizarpos.mall.model.open.SelfTicketAddInput;
import cn.congine.wizarpos.mall.model.open.SelfTicketAddOutput;
import cn.congine.wizarpos.mall.model.open.DzxShekeQrInput;
import cn.congine.wizarpos.mall.model.open.TicketDefInfoInput;
import cn.congine.wizarpos.mall.model.open.TicketDefInfoOutput;
import cn.congine.wizarpos.mall.model.open.AccessTokenOutput.Result;
import cn.congine.wizarpos.mall.service.MrtMerchantDefService;
import cn.congine.wizarpos.mall.service.MyOnlineActivityDetailService;
import cn.congine.wizarpos.mall.service.MyOnlineActivityHistoryService;
import cn.congine.wizarpos.mall.service.MyOnlineActivityService;
import cn.congine.wizarpos.mall.service.MyOpenidRelationService;
import cn.congine.wizarpos.mall.service.MyRedEnvelopesService;
import cn.congine.wizarpos.mall.service.MyShakeService;
import cn.congine.wizarpos.mall.service.SysInTokenService;
import cn.congine.wizarpos.mall.service.impl.WPosHttpClient;
import cn.congine.wizarpos.mall.service.impl.WizarposOpenRestClient;
import cn.congine.wizarpos.mall.service.impl.WizarposUserOpenRestClient;
import cn.congine.wizarpos.mall.service.impl.WxHttpClient;
import cn.congine.wizarpos.mall.utils.Function;
import cn.congine.wizarpos.mall.utils.SysConstants;
import cn.congine.wizarpos.mall.utils.Utils;
import cn.congine.wizarpos.mall.utils.WxSignUtil;

import com.alibaba.fastjson.JSONObject;

@Controller
@RequestMapping(value = "/ibeacon")
public class IbeaconAction {
	private final Log log = LogFactory.getLog(getClass());

	@Resource(name = "messageSource")
	private MessageSource messageSource;

	@Autowired
	private WPosHttpClient wposHttpClient;
	@Autowired
	private WxHttpClient wxHttpClient;
	@Autowired
	private WizarposOpenRestClient wizarposOpenRestClient;
	@Autowired
	private WizarposUserOpenRestClient wizarposUserOpenRestClient;
	@Autowired
	private MyOnlineActivityService myOnlineActivityService;
	@Autowired
	private MyShakeService myShakeService;
	@Autowired
	private MyOnlineActivityHistoryService myOnlineActivityHistoryService;
	@Autowired
	private MyOpenidRelationService myOpenidRelationService;
	@Autowired
	private MrtMerchantDefService mrtMerchantDefService;
	@Autowired
	private MyRedEnvelopesService myRedEnvelopesService;
	@Autowired
	private MyOnlineActivityDetailService myOnlineActivityDetailService;
	@Autowired
	private SysInTokenService sysInTokenService;

	// 处理成功
	private final String SUCCESS = "0";
	private final String EXIST = "60006";
	private List<WeightCategory> categorys = null;
	private static Random random = new Random();

	private void initData(List<MyShake> myShakeList) {
		categorys = new ArrayList<WeightCategory>();
		for (MyShake myShake : myShakeList) {
			if (myShake.getTicketNum() != null && myShake.getTicketQz() != null) {
				if (myShake.getTicketNum() != 0) {
					WeightCategory wc = new WeightCategory(
							myShake.getTicketId(), Integer.parseInt(myShake
									.getTicketQz()));
					categorys.add(wc);
				}

			}

		}
	}

	/**
	 * 摇一摇券列表
	 * 
	 * @param openId
	 * @param mid
	 * @return
	 */
	@RequestMapping(value = "/toList", method = RequestMethod.GET)
	@ResponseBody
	public ModelAndView toList(
			@RequestParam(value = "mid", required = true) String mid,
			@RequestParam(value = "ticketDefId", required = true) String ticketDefId,
			Model model, HttpServletRequest httpRequest) {
		String openId = (String) httpRequest.getSession()
				.getAttribute("openId");
		if (StringUtils.isEmpty(openId)) {// session过期，跳转到登录注册页面
			return new ModelAndView("forward:/vip/login");
		}
		model.addAttribute("mid", mid);
		model.addAttribute("openId", openId);

		MerchantDefQueryInput merchantDeQfueryInput = new MerchantDefQueryInput();
		merchantDeQfueryInput.setMid(mid);
		MerchantDefQueryOutput merchantDefQueryOutput = (MerchantDefQueryOutput) wizarposOpenRestClient
				.post(merchantDeQfueryInput, "/merchantdef/info",
						MerchantDefQueryOutput.class);

		model.addAttribute("marchantName", merchantDefQueryOutput.getResult()
				.getMerchantName());
		model.addAttribute("logoImage", merchantDefQueryOutput.getResult()
				.getLogoImage());

		TicketDefInfoInput ticketDefInfoInput = new TicketDefInfoInput();
		ticketDefInfoInput
				.setTicketDefIds(Arrays.asList(ticketDefId.split(",")));
		TicketDefInfoOutput ticketDefInfoOutput = (TicketDefInfoOutput) wizarposOpenRestClient
				.post(ticketDefInfoInput, "/wechart/ticketdef/info",
						TicketDefInfoOutput.class);

		List<MrtTicketDef> ticketDefList = ticketDefInfoOutput.getResult();
		for (MrtTicketDef ticketDef : ticketDefList) {
			if ("0".equals(ticketDef.getUsedFlag())) {// 卡券已经停用
				continue;
			}
			String validPeriod = ticketDef.getValidPeriod();
			if ("-1".equals(validPeriod)) {
				ticketDef.setValidPeriod("永久有效");
			} else {
				SimpleDateFormat sdf = new SimpleDateFormat(
						"yyyy-MM-dd HH:mm:ss");
				Date date = null;
				try {
					date = sdf.parse(ticketDef.getCreateTime());
				} catch (ParseException e) {
					log.error(e.getMessage());
				}
				Date expriyTime = Function.addDay(date,
						Integer.valueOf(validPeriod));
				ticketDef.setValidPeriod(sdf.format(expriyTime));
			}
		}

		model.addAttribute("ticketDefList", ticketDefList);

		return new ModelAndView("ibeacon/ibeacon_list");
	}

	/**
	 * 摇一摇单张券，会员券，微信券，红包分享
	 * 
	 * @param openId
	 * @param mid
	 * @return
	 */
	@RequestMapping(value = "/toOne", method = RequestMethod.GET)
	@ResponseBody
	public ModelAndView toOne(
			@RequestParam(value = "mid", required = true) String mid,
			@RequestParam(value = "ticketDefId", required = true) String ticketDefId,
			Model model, HttpServletRequest httpRequest) {
		String openId = (String) httpRequest.getSession()
				.getAttribute("openId");
		if (StringUtils.isEmpty(openId)) {// session过期，跳转到登录注册页面
			return new ModelAndView("forward:/vip/login");
		}
		Utils.setSessionToken(httpRequest);

		TicketDefInfoInput ticketDefInfoInput = new TicketDefInfoInput();
		ticketDefInfoInput.setTicketDefIds(Arrays.asList(ticketDefId));
		TicketDefInfoOutput ticketDefInfoOutput = (TicketDefInfoOutput) wizarposOpenRestClient
				.post(ticketDefInfoInput, "/wechart/ticketdef/info",
						TicketDefInfoOutput.class);
		MrtTicketDef ticketDef = null;
		if (ticketDefInfoOutput == null
				|| SysConstants.OPEN_ERROR
						.equals(ticketDefInfoOutput.getCode())) {
			return new ModelAndView("error").addObject("err_message", "系统错误");
		} else {
			ticketDef = ticketDefInfoOutput.getResult().get(0);
		}
		if ("0".equals(ticketDef.getUsedFlag())) {// 卡券已经停用
			return new ModelAndView("error").addObject("err_message", "暂无优惠券");
		}
		model.addAttribute("mid", mid);
		model.addAttribute("openId", openId);

		MerchantDefQueryInput merchantDeQfueryInput = new MerchantDefQueryInput();
		merchantDeQfueryInput.setMid(mid);
		MerchantDefQueryOutput merchantDefQueryOutput = (MerchantDefQueryOutput) wizarposOpenRestClient
				.post(merchantDeQfueryInput, "/merchantdef/info",
						MerchantDefQueryOutput.class);
		MerchantDef marchant = null;
		if (merchantDefQueryOutput == null
				|| SysConstants.OPEN_ERROR.equals(merchantDefQueryOutput
						.getCode())) {
			return new ModelAndView("error").addObject("err_message", "系统错误");
		} else if (SysConstants.NO_MERCHANT_CODE.equals(merchantDefQueryOutput
				.getCode())) {
			return new ModelAndView("error").addObject("err_message",
					merchantDefQueryOutput.getMessage());
		} else {
			marchant = merchantDefQueryOutput.getResult();
		}
		model.addAttribute("marchantName", marchant.getMerchantName());
		model.addAttribute("logoImage", marchant.getLogoImage());

		model.addAttribute("ticketId", ticketDef.getId());
		model.addAttribute("ticketName", ticketDef.getTicketName());
		model.addAttribute("description", ticketDef.getDescription());
		String validPeriod = ticketDef.getValidPeriod();
		if ("-1".equals(validPeriod)) {
			String expriyTime = "永久有效";
			model.addAttribute("expriyTime", expriyTime);
		} else {
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			Date date = null;
			try {
				date = sdf.parse(ticketDef.getCreateTime());
			} catch (ParseException e) {
				log.error(e.getMessage());
			}
			Date expriyTime = Function.addDay(date,
					Integer.valueOf(validPeriod));
			model.addAttribute("expriyTime", sdf.format(expriyTime));
		}

		if (ticketDef.getWxFlag() == '1' && ticketDef.getWxCodeId() != null) {// 微信券
			model.addAttribute("wxCodeId", ticketDef.getWxCodeId());

			// 请求微信 js api的完整页面地址
			String dns = messageSource.getMessage(SysConstants.SERVICE_DNS,
					null, Locale.ENGLISH);
			model.addAttribute("dns", dns);

			String baseUrl = "http://"
					+ dns
					+ httpRequest.getSession().getServletContext()
							.getContextPath();
			StringBuffer tmpUrl = new StringBuffer();
			tmpUrl.append(baseUrl);
			tmpUrl.append("/ibeacon/toOne");
			tmpUrl.append("?wechat_card_js=1");
			tmpUrl.append("&mid=").append(mid);
			tmpUrl.append("&ticketDefId=").append(ticketDefId);
			String url = tmpUrl.toString();
			// 请求微信api的ticket
			String jsTicket = null;
			AccessTokenInput jsInput = new AccessTokenInput();
			jsInput.setMid(mid);
			CommonResultOutput jsOutput = (CommonResultOutput) wizarposOpenRestClient
					.post(jsInput, "/weixin/ticket/js",
							CommonResultOutput.class);
			if (jsOutput == null
					|| SysConstants.OPEN_ERROR.equals(jsOutput.getCode())) {
				return new ModelAndView("error").addObject("err_message",
						SysConstants.OPEN_ERROR);
			} else if (SysConstants.NO_MERCHANT_CODE.equals(jsOutput.getCode())) {
				return new ModelAndView("error").addObject("err_message",
						SysConstants.NO_MERCHANT);
			} else {
				Map<String, String> result = (Map<String, String>) jsOutput
						.getResult();
				jsTicket = result.get("ticket");
			}
			// 微信 js config 签名
			Map<String, String> ret = WxSignUtil.commonSign(jsTicket, url,
					WxSignUtil.createTimestamp());
			model.addAllAttributes(ret);

			// 请求微信card api的ticket
			String cardTicket = null;
			jsOutput = (CommonResultOutput) wizarposOpenRestClient.post(
					jsInput, "/weixin/ticket/card", CommonResultOutput.class);
			if (jsOutput != null
					&& SysConstants.OPEN_SUCCESS.equals(jsOutput.getCode())) {
				Map<String, String> result = (Map<String, String>) jsOutput
						.getResult();
				cardTicket = result.get("ticket");
			} else if (jsOutput != null
					&& SysConstants.NO_MERCHANT_CODE.equals(jsOutput.getCode())) {
				return new ModelAndView("error").addObject("err_message",
						SysConstants.NO_MERCHANT);
			} else {
				return new ModelAndView("error").addObject("err_message",
						SysConstants.OPEN_ERROR);
			}
			try {
				String signature = WxSignUtil.extSign(cardTicket,
						ticketDef.getWxCodeId(), ret.get("timestamp"), "", "");
				model.addAttribute("ext_signature", signature);
			} catch (Exception e) {
				log.error(e.getMessage());
				return new ModelAndView("ibeacon/ibeacon");
			}
			model.addAttribute("appId", marchant.getWeixinAppId());
			return new ModelAndView("ibeacon/ibeacon_wx");

		} else if (ticketDef.getWxFlag() == '2') {
			// 请求微信 js api的完整页面地址
			String dns = messageSource.getMessage(SysConstants.SERVICE_DNS,
					null, Locale.ENGLISH);
			model.addAttribute("dns", dns);

			String baseUrl = "http://"
					+ dns
					+ httpRequest.getSession().getServletContext()
							.getContextPath();
			StringBuffer tmpUrl = new StringBuffer();
			tmpUrl.append(baseUrl);
			tmpUrl.append("/ibeacon/toOne");
			tmpUrl.append("?wechat_card_js=1");
			tmpUrl.append("&mid=").append(mid);
			tmpUrl.append("&ticketDedId=").append(ticketDefId);
			String url = tmpUrl.toString();
			// 请求微信api的ticket
			String jsTicket = null;
			AccessTokenInput jsInput = new AccessTokenInput();
			jsInput.setMid(mid);
			CommonResultOutput jsOutput = (CommonResultOutput) wizarposOpenRestClient
					.post(jsInput, "/weixin/ticket/js",
							CommonResultOutput.class);
			if (jsOutput == null
					|| SysConstants.OPEN_ERROR.equals(jsOutput.getCode())) {
				return new ModelAndView("error").addObject("err_message",
						SysConstants.OPEN_ERROR);
			} else if (SysConstants.NO_MERCHANT_CODE.equals(jsOutput.getCode())) {
				return new ModelAndView("error").addObject("err_message",
						SysConstants.NO_MERCHANT);
			} else {
				Map<String, String> result = (Map<String, String>) jsOutput
						.getResult();
				jsTicket = result.get("ticket");
			}
			// 微信 js config 签名
			Map<String, String> ret = WxSignUtil.commonSign(jsTicket, url,
					WxSignUtil.createTimestamp());
			model.addAllAttributes(ret);

			return new ModelAndView("ibeacon/ibeacon_hongbao");
		}

		return new ModelAndView("ibeacon/ibeacon");
	}

	/**
	 * 摇一摇单张微信券
	 * 
	 * @param openId
	 * @param mid
	 * @return
	 */
	@RequestMapping(value = "/toOneWx", method = RequestMethod.GET)
	@ResponseBody
	public ModelAndView toOneWx(
			@RequestParam(value = "mid", required = true) String mid,
			@RequestParam(value = "ticketDefId", required = true) String ticketDefId,
			Model model, HttpServletRequest httpRequest) {
		String openId = (String) httpRequest.getSession()
				.getAttribute("openId");
		if (StringUtils.isEmpty(openId)) {// session过期，跳转到登录注册页面
			return new ModelAndView("forward:/vip/login");
		}
		Utils.setSessionToken(httpRequest);

		TicketDefInfoInput ticketDefInfoInput = new TicketDefInfoInput();
		ticketDefInfoInput.setTicketDefIds(Arrays.asList(ticketDefId));
		TicketDefInfoOutput ticketDefInfoOutput = (TicketDefInfoOutput) wizarposOpenRestClient
				.post(ticketDefInfoInput, "/wechart/ticketdef/info",
						TicketDefInfoOutput.class);
		MrtTicketDef ticketDef = null;
		if (ticketDefInfoOutput == null
				|| SysConstants.OPEN_ERROR
						.equals(ticketDefInfoOutput.getCode())) {
			return new ModelAndView("error").addObject("err_message", "系统错误");
		} else {
			ticketDef = ticketDefInfoOutput.getResult().get(0);
		}

		if ("0".equals(ticketDef.getUsedFlag())) {// 卡券已经停用
			return new ModelAndView("error").addObject("err_message", "暂无优惠券");
		}

		model.addAttribute("mid", mid);
		model.addAttribute("openId", openId);

		MerchantDefQueryInput merchantDeQfueryInput = new MerchantDefQueryInput();
		merchantDeQfueryInput.setMid(mid);
		MerchantDefQueryOutput merchantDefQueryOutput = (MerchantDefQueryOutput) wizarposOpenRestClient
				.post(merchantDeQfueryInput, "/merchantdef/info",
						MerchantDefQueryOutput.class);
		MerchantDef marchant = null;
		if (merchantDefQueryOutput == null
				|| SysConstants.OPEN_ERROR.equals(merchantDefQueryOutput
						.getCode())) {
			return new ModelAndView("error").addObject("err_message", "系统错误");
		} else if (SysConstants.NO_MERCHANT_CODE.equals(merchantDefQueryOutput
				.getCode())) {
			return new ModelAndView("error").addObject("err_message",
					merchantDefQueryOutput.getMessage());
		} else {
			marchant = merchantDefQueryOutput.getResult();
		}

		model.addAttribute("marchantName", marchant.getMerchantName());
		model.addAttribute("logoImage", marchant.getLogoImage());

		model.addAttribute("ticketId", ticketDef.getId());
		model.addAttribute("ticketName", ticketDef.getTicketName());
		model.addAttribute("description", ticketDef.getDescription());
		String validPeriod = ticketDef.getValidPeriod();
		if ("-1".equals(validPeriod)) {
			String expriyTime = "永久有效";
			model.addAttribute("expriyTime", expriyTime);
		} else {
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			Date date = null;
			try {
				date = sdf.parse(ticketDef.getCreateTime());
			} catch (ParseException e) {
				log.error(e.getMessage());
			}
			Date expriyTime = Function.addDay(date,
					Integer.valueOf(validPeriod));
			model.addAttribute("expriyTime", sdf.format(expriyTime));
		}

		if (ticketDef.getWxFlag() == '1' && ticketDef.getWxCodeId() != null) {// 微信券
			model.addAttribute("wxCodeId", ticketDef.getWxCodeId());

			// 请求微信 js api的完整页面地址
			String dns = messageSource.getMessage(SysConstants.SERVICE_DNS,
					null, Locale.ENGLISH);
			model.addAttribute("dns", dns);

			String baseUrl = "http://"
					+ dns
					+ httpRequest.getSession().getServletContext()
							.getContextPath();
			StringBuffer tmpUrl = new StringBuffer();
			tmpUrl.append(baseUrl);
			tmpUrl.append("/ibeacon/toOneWx");
			tmpUrl.append("?wechat_card_js=1");
			tmpUrl.append("&mid=").append(mid);
			tmpUrl.append("&ticketDefId=").append(ticketDefId);
			String url = tmpUrl.toString();
			// 请求微信api的ticket
			String jsTicket = null;
			AccessTokenInput jsInput = new AccessTokenInput();
			jsInput.setMid(mid);
			CommonResultOutput jsOutput = (CommonResultOutput) wizarposOpenRestClient
					.post(jsInput, "/weixin/ticket/js",
							CommonResultOutput.class);
			if (jsOutput == null
					|| SysConstants.OPEN_ERROR.equals(jsOutput.getCode())) {
				return new ModelAndView("error").addObject("err_message",
						SysConstants.OPEN_ERROR);
			} else if (SysConstants.NO_MERCHANT_CODE.equals(jsOutput.getCode())) {
				return new ModelAndView("error").addObject("err_message",
						SysConstants.NO_MERCHANT);
			} else {
				Map<String, String> result = (Map<String, String>) jsOutput
						.getResult();
				jsTicket = result.get("ticket");
			}
			// 微信 js config 签名
			Map<String, String> ret = WxSignUtil.commonSign(jsTicket, url,
					WxSignUtil.createTimestamp());
			model.addAllAttributes(ret);

			// 请求微信card api的ticket
			String cardTicket = null;
			jsOutput = (CommonResultOutput) wizarposOpenRestClient.post(
					jsInput, "/weixin/ticket/card", CommonResultOutput.class);
			if (jsOutput != null
					&& SysConstants.OPEN_SUCCESS.equals(jsOutput.getCode())) {
				Map<String, String> result = (Map<String, String>) jsOutput
						.getResult();
				cardTicket = result.get("ticket");
			} else if (jsOutput != null
					&& SysConstants.NO_MERCHANT_CODE.equals(jsOutput.getCode())) {
				return new ModelAndView("error").addObject("err_message",
						SysConstants.NO_MERCHANT);
			} else {
				return new ModelAndView("error").addObject("err_message",
						SysConstants.OPEN_ERROR);
			}

			try {
				String signature = WxSignUtil.extSign(cardTicket,
						ticketDef.getWxCodeId(), ret.get("timestamp"), "", "");
				model.addAttribute("ext_signature", signature);
			} catch (Exception e) {
				log.error(e.getMessage());
				return new ModelAndView("error").addObject("err_message",
						e.getMessage());
			}

			model.addAttribute("appId", marchant.getWeixinAppId());
			return new ModelAndView("ibeacon/ibeacon_wx_gz");
		}

		return new ModelAndView("error").addObject("err_message", "系统错误");
	}

	/**
	 * 领取会员券
	 * 
	 * @param mid
	 * @param ticketId
	 * @param openId
	 * @return
	 */
	@RequestMapping(value = "/receive")
	public @ResponseBody String receive(
			@RequestParam(value = "mid", required = true) String mid,
			@RequestParam(value = "openId", required = true) String openId,
			@RequestParam(value = "ticketDefId", required = true) String ticketDefId,
			@RequestParam(value = "token", required = true) String token,
			HttpServletRequest httpRequest) {
		if (Utils.isRepeatSubmit(httpRequest, token)) {
			return "1";
		}
		// 请求开放平台
		SelfTicketAddInput input = new SelfTicketAddInput();
		input.setMid(mid);
		input.setOpenId(openId);
		input.setTicketId(ticketDefId);
		input.setWxAdded('0');
		input.setHbShared("0");
		input.setRemark("摇一摇");
		String dns = messageSource.getMessage(SysConstants.SERVICE_DNS, null,
				Locale.ENGLISH);
		// 由开放平台替换 APPID
		String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid="
				+ "APPID"
				+ "&redirect_uri=http%3a%2f%2f"
				+ dns
				+ "%2fwizarpos-mall-sole%2foauth%2fhongbao_enter&response_type=code&scope=snsapi_base&state="
				+ ticketDefId + "#wechat_redirect";
		input.setUrl(url);
		SelfTicketAddOutput output = (SelfTicketAddOutput) wizarposOpenRestClient
				.post(input, "/wechart/selfTicketAdd",
						SelfTicketAddOutput.class);
		if (output == null || "-1".equals(output.getCode())
				|| "60068".equals(output.getCode())) {// 60068 注册会员卡失败, -1
														// 处理失败，系统错误
			return "2";
		} else if ("60062".equals(output.getCode())
				|| "60069".equals(output.getCode())) {// 用户已经领取过此类红包，不可再次领取
			return "3";
		} else {// 0 操作成功
				// 记录创建完删除session中的token
			Utils.removeSessionToken(httpRequest);
			return "0";
		}

	}

	/**
	 * 授权的单张微信券，自定义code
	 * 
	 * @param openId
	 * @param mid
	 * @return
	 */
	@RequestMapping(value = "/onewx4auth", method = RequestMethod.GET)
	@ResponseBody
	public ModelAndView oneWx4Auth(
			@RequestParam(value = "mid", required = true) String mid,
			@RequestParam(value = "ticketDefId", required = true) String ticketDefId,
			Model model, HttpServletRequest httpRequest) {
		String openId = (String) httpRequest.getSession()
				.getAttribute("openId");
		if (StringUtils.isEmpty(openId)) {// session过期，跳转到登录注册页面
			return new ModelAndView("forward:/vip/login");
		}
		Utils.setSessionToken(httpRequest);

		TicketDefInfoInput ticketDefInfoInput = new TicketDefInfoInput();
		ticketDefInfoInput.setTicketDefIds(Arrays.asList(ticketDefId));
		TicketDefInfoOutput ticketDefInfoOutput = (TicketDefInfoOutput) wizarposOpenRestClient
				.post(ticketDefInfoInput, "/wechart/ticketdef/info",
						TicketDefInfoOutput.class);
		MrtTicketDef ticketDef = null;
		if (ticketDefInfoOutput == null
				|| SysConstants.OPEN_ERROR
						.equals(ticketDefInfoOutput.getCode())) {
			return new ModelAndView("error").addObject("err_message", "系统错误");
		} else {
			ticketDef = ticketDefInfoOutput.getResult().get(0);
		}

		if ("0".equals(ticketDef.getUsedFlag())) {// 卡券已经停用
			return new ModelAndView("error").addObject("err_message", "优惠券已停用");
		}

		model.addAttribute("mid", mid);
		model.addAttribute("openId", openId);

		MerchantDefQueryInput merchantDeQfueryInput = new MerchantDefQueryInput();
		merchantDeQfueryInput.setMid(mid);
		MerchantDefQueryOutput merchantDefQueryOutput = (MerchantDefQueryOutput) wizarposOpenRestClient
				.post(merchantDeQfueryInput, "/merchantdef/info",
						MerchantDefQueryOutput.class);
		MerchantDef marchant = null;
		if (merchantDefQueryOutput == null
				|| SysConstants.OPEN_ERROR.equals(merchantDefQueryOutput
						.getCode())) {
			return new ModelAndView("error").addObject("err_message", "系统错误");
		} else if (SysConstants.NO_MERCHANT_CODE.equals(merchantDefQueryOutput
				.getCode())) {
			return new ModelAndView("error").addObject("err_message",
					merchantDefQueryOutput.getMessage());
		} else {
			marchant = merchantDefQueryOutput.getResult();
		}

		model.addAttribute("marchantName", marchant.getMerchantName());
		model.addAttribute("logoImage", marchant.getLogoImage());

		model.addAttribute("ticketId", ticketDef.getId());
		model.addAttribute("ticketName", ticketDef.getTicketName());
		model.addAttribute("description", ticketDef.getDescription());
		String validPeriod = ticketDef.getValidPeriod();
		if ("-1".equals(validPeriod)) {
			String expriyTime = "永久有效";
			model.addAttribute("expriyTime", expriyTime);
		} else {
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			Date date = null;
			try {
				date = sdf.parse(ticketDef.getCreateTime());
			} catch (ParseException e) {
				log.error(e.getMessage());
			}
			Date expriyTime = Function.addDay(date,
					Integer.valueOf(validPeriod));
			model.addAttribute("expriyTime", sdf.format(expriyTime));
		}

		if (ticketDef.getWxFlag() == '1' && ticketDef.getWxCodeId() != null) {// 微信券
			model.addAttribute("wxCodeId", ticketDef.getWxCodeId());

			// 请求微信 js api的完整页面地址
			String dns = messageSource.getMessage(SysConstants.SERVICE_DNS,
					null, Locale.ENGLISH);
			model.addAttribute("dns", dns);

			String baseUrl = "http://"
					+ dns
					+ httpRequest.getSession().getServletContext()
							.getContextPath();
			StringBuffer tmpUrl = new StringBuffer();
			tmpUrl.append(baseUrl);
			tmpUrl.append("/ibeacon/onewx4auth");
			tmpUrl.append("?wechat_card_js=1");
			tmpUrl.append("&mid=").append(mid);
			tmpUrl.append("&ticketDefId=").append(ticketDefId);
			String url = tmpUrl.toString();
			// 请求微信api的ticket
			String jsTicket = null;
			AccessTokenInput jsInput = new AccessTokenInput();
			jsInput.setMid(mid);
			CommonResultOutput jsOutput = (CommonResultOutput) wizarposOpenRestClient
					.post(jsInput, "/weixin/ticket/js",
							CommonResultOutput.class);
			if (jsOutput == null
					|| SysConstants.OPEN_ERROR.equals(jsOutput.getCode())) {
				return new ModelAndView("error").addObject("err_message",
						SysConstants.OPEN_ERROR);
			} else if (SysConstants.NO_MERCHANT_CODE.equals(jsOutput.getCode())) {
				return new ModelAndView("error").addObject("err_message",
						SysConstants.NO_MERCHANT);
			} else {
				Map<String, String> result = (Map<String, String>) jsOutput
						.getResult();
				jsTicket = result.get("ticket");
			}
			// 微信 js config 签名
			Map<String, String> ret = WxSignUtil.commonSign(jsTicket, url,
					WxSignUtil.createTimestamp());
			model.addAllAttributes(ret);

			String code = wposHttpClient.getTicketCode(mid);
			model.addAttribute("code", code);
			// 请求微信card api的ticket
			String cardTicket = null;
			jsOutput = (CommonResultOutput) wizarposOpenRestClient.post(
					jsInput, "/weixin/ticket/card", CommonResultOutput.class);
			if (jsOutput != null
					&& SysConstants.OPEN_SUCCESS.equals(jsOutput.getCode())) {
				Map<String, String> result = (Map<String, String>) jsOutput
						.getResult();
				cardTicket = result.get("ticket");
			} else if (jsOutput != null
					&& SysConstants.NO_MERCHANT_CODE.equals(jsOutput.getCode())) {
				return new ModelAndView("error").addObject("err_message",
						SysConstants.NO_MERCHANT);
			} else {
				return new ModelAndView("error").addObject("err_message",
						SysConstants.OPEN_ERROR);
			}
			try {
				String signature = WxSignUtil
						.extSign(cardTicket, ticketDef.getWxCodeId(),
								ret.get("timestamp"), code, "");
				model.addAttribute("ext_signature", signature);
			} catch (Exception e) {
				log.error(e.getMessage());
				return new ModelAndView("error").addObject("err_message",
						e.getMessage());
			}

			model.addAttribute("appId", marchant.getWeixinAppId());
			return new ModelAndView("ibeacon/ibeacon_wx_auth");
		}

		return new ModelAndView("error").addObject("err_message", "系统错误");
	}

	/**
	 * 在慧银系统创建授权微信卡券的对应券实例
	 * 
	 * @param mid
	 * @param ticketId
	 * @param openId
	 * @return
	 */
	@RequestMapping(value = "/receive4auth", method = RequestMethod.GET)
	public @ResponseBody String receive4auth(
			@RequestParam(value = "mid", required = true) String mid,
			@RequestParam(value = "openId", required = true) String openId,
			@RequestParam(value = "code", required = true) String code,
			@RequestParam(value = "ticketDefId", required = true) String ticketDefId) {
		// 请求开放平台， 为用户创建卡券记录
		SelfTicketAddInput input = new SelfTicketAddInput();
		input.setMid(mid);
		input.setOpenId(openId);
		input.setTicketId(ticketDefId);
		input.setTicketNo(code);
		input.setWxAdded('1');
		input.setHbShared("0");
		input.setRemark("摇一摇");
		SelfTicketAddOutput output = (SelfTicketAddOutput) wizarposOpenRestClient
				.post(input, "/wechart/selfTicketAdd",
						SelfTicketAddOutput.class);
		if (output != null && "0".equals(output.getCode())) {// 操作成功
			return "0";
		} else {// 操作失败，返回错误码
			return output.getCode();
		}
	}

	/**
	 * 摇券
	 * 
	 * @param mid
	 *            东志信的慧商户号
	 * @param openId
	 *            东志信公众号用户的openid
	 * @return
	 */
	@RequestMapping(value = "/shake")
	public ModelAndView shake(
			@RequestParam(value = "mid", required = true) String mid,
			@RequestParam(value = "openId", required = true) String openId,
			Model model) {

		model.addAttribute("mid", mid);
		model.addAttribute("openId", openId);

		MyOnlineActivity myOnlineActivity = myOnlineActivityService
				.getMyOnlineActivityByMid(mid);

		MyOnlineActivityHistory myOnlineActivityHistory = myOnlineActivityHistoryService
				.getMyOnlineActivityHistoryByOpenId(openId,
						myOnlineActivity.getId());

		if (myOnlineActivityHistory == null) {

			myOnlineActivityHistory = new MyOnlineActivityHistory();

			myOnlineActivityHistory.setMid(mid);
			myOnlineActivityHistory.setOnlineActivityId(myOnlineActivity
					.getId());
			myOnlineActivityHistory.setOpenId(openId);
			myOnlineActivityHistory.setHaveReceivedNum(0l);
			myOnlineActivityHistoryService.save(myOnlineActivityHistory);
		}

		model.addAttribute("count", myOnlineActivity.getMaxNum()
				- myOnlineActivityHistory.getHaveReceivedNum());

		return new ModelAndView("onlineActivity/yaoyiyao");
	}

	/**
	 * 手机短息版本摇一摇页面功能支�?
	 * 
	 * @param PhoneNumber
	 * @return Verification code
	 */
	@RequestMapping(value = "/h5shake", method = RequestMethod.POST)
	public @ResponseBody String h5shake(
			@RequestParam(value = "mid", required = true) String mid,
			@RequestParam(value = "openId", required = true) String openId,
			Model model, HttpServletRequest httpRequest) {

		JSONObject obj = new JSONObject();
		Utils.setSessionToken(httpRequest);
		// 获取此商户开启的线上活动, 一个商户只能开启一�?
		MyOnlineActivity myOnlineActivity = myOnlineActivityService
				.getMyOnlineActivityByMid(mid);

		Long count = 0l;
		if (myOnlineActivity != null) {
			// 查询活动流水看是否已经领取满�?
			MyOnlineActivityHistory myOnlineActivityHistory = myOnlineActivityHistoryService
					.getMyOnlineActivityHistoryByOpenId(openId,
							myOnlineActivity.getId());

			if (myOnlineActivityHistory == null) {

				myOnlineActivityHistory = new MyOnlineActivityHistory();

				myOnlineActivityHistory.setMid(mid);
				myOnlineActivityHistory.setOnlineActivityId(myOnlineActivity
						.getId());
				myOnlineActivityHistory.setOpenId(openId);
				myOnlineActivityHistory.setHaveReceivedNum(1l);
				myOnlineActivityHistoryService.save(myOnlineActivityHistory);

				count = myOnlineActivity.getMaxNum() - 1l;

			} else {

				// 判断当前的微信账户是否已经领取完它对应的份额
				Long haveReceivedNum = myOnlineActivityHistory
						.getHaveReceivedNum();
				// 活动允许次数
				Long maxNum = myOnlineActivity.getMaxNum();
				if (maxNum <= haveReceivedNum) {
					// 领取次数已用�?

					obj.put("code", "-1");
					return obj.toString();
				} else {

					myOnlineActivityHistory
							.setHaveReceivedNum(myOnlineActivityHistory
									.getHaveReceivedNum() + 1);

					myOnlineActivityHistoryService
							.save(myOnlineActivityHistory);

					count = myOnlineActivity.getMaxNum()
							- myOnlineActivityHistory.getHaveReceivedNum();
				}
			}
		} else {
			obj.put("code", "-3");
			return obj.toString();

		}

		// 查询开放平台是否已经注册慧银会�?
		RegisteredMemberQueryInput input = new RegisteredMemberQueryInput();
		input.setMid(mid);
		input.setOpenId(openId);
		RegisteredMemberQueryOutput ouptut = (RegisteredMemberQueryOutput) wizarposOpenRestClient
				.post(input, "/wechart/registerMember",
						RegisteredMemberQueryOutput.class);
		String cardNo = null;
		String mobileNo = null;
		// 判断是否为慧银注册会�?
		if (SUCCESS.equals(ouptut.getCode())) {
			if (ouptut.getResult() != null
					&& ouptut.getResult().getCardNo() != null) {
				// 是慧银注册会�?
				cardNo = ouptut.getResult().getCardNo();
				if (ouptut.getResult().getMobileNo() != null
						&& !"".equals(ouptut.getResult().getMobileNo())) {
					mobileNo = ouptut.getResult().getMobileNo();
				}
			}
		} else if (EXIST.equals(ouptut.getCode())) {
			// 是慧银注册会�?
			cardNo = ouptut.getResult().getCardNo();
			if (ouptut.getResult().getMobileNo() != null
					&& !"".equals(ouptut.getResult().getMobileNo())) {
			}
		}

		// 线上摇券获取券逻辑
		String ticketDefId = null;

		List<String> ticketMids = null;
		// 获取开启活动的所有优惠券
		List<MyShake> myShakeList = myShakeService.getMyShakeList(mid,
				myOnlineActivity.getId(), ticketMids);

		if (myShakeList == null) {
			//
			obj.put("code", "-4");
			return obj.toString();
		}

		initData(myShakeList);

		Integer weightSum = 0;
		for (WeightCategory wc : categorys) {
			weightSum += wc.getWeight();
		}

		if (weightSum <= 0) {
			// 活动已结束
			obj.put("code", "-2");
			return obj.toString();
		}
		Integer n = random.nextInt(weightSum); // n in [0, weightSum)

		Integer m = 0;
		for (WeightCategory wc : categorys) {
			if (m <= n && n < m + wc.getWeight()) {
				ticketDefId = wc.getCategory();
				break;
			}
			m += wc.getWeight();
		}

		if (StringUtils.isEmpty(ticketDefId)) {
			obj.put("code", "-4");
			return obj.toString();
		}

		// 获取对应的券信息
		MyShake myShake = myShakeService.getMyShakeByid(ticketDefId, mid,
				myOnlineActivity.getId());

		String server_token = (String) httpRequest.getSession().getAttribute(
				SysConstants.SESSION_TOKEN);

		obj.put("code", "0");
		obj.put("count", count);
		obj.put("cardNo", cardNo);
		obj.put("mobileNo", mobileNo);
		obj.put("ticketId", myShake.getTicketId());
		obj.put("name", myShake.getTicketName());
		obj.put("validTime", myShake.getValidTime());
		obj.put("ticketId", ticketDefId);
		obj.put("onlineActivityId", myOnlineActivity.getId());
		obj.put("openId", openId);
		obj.put("mid", mid);
		obj.put("token", server_token);

		return obj.toString();
	}

	/**
	 * 获取短信验证
	 * 
	 * @param PhoneNumber
	 * @return Verification code
	 */
	@RequestMapping(value = "/getVerificationCode", method = RequestMethod.POST)
	public @ResponseBody String getVerificationCode(
			@RequestParam(value = "phoneNumber", required = true) String phoneNumber,
			Model model, HttpServletRequest httpRequest) {
		Utils.setSessionToken(httpRequest);
		// 如果不是发送短信验证码
		DxChartMemberRegisterInput dxInput = new DxChartMemberRegisterInput();
		dxInput.setLoginName(phoneNumber);

		DxChartMemberRegisterOutput dxOuptut = (DxChartMemberRegisterOutput) wizarposUserOpenRestClient
				.post(dxInput, "/v1_0/client/user/register",
						DxChartMemberRegisterOutput.class);

		String server_token = (String) httpRequest.getSession().getAttribute(
				SysConstants.SESSION_TOKEN);
		JSONObject obj = new JSONObject();
		obj.put("code", dxOuptut.getCode());
		obj.put("token", server_token);

		return obj.toString();
	}

	/**
	 * 获取摇到的券
	 * 
	 * @param mid
	 * @param verificationCode
	 *            验证�?
	 * @param phoneNumber
	 *            手机号码
	 * @param openId
	 *            微信ID
	 * @return
	 */
	@RequestMapping(value = "/receiveShakeVoucher")
	public @ResponseBody String receiveShakeVoucher(
			@RequestParam(value = "mid", required = true) String mid,
			@RequestParam(value = "verificationCode", required = false) String verificationCode,
			@RequestParam(value = "phoneNumber", required = false) String phoneNumber,
			@RequestParam(value = "ticketId", required = true) String ticketId,
			@RequestParam(value = "onlineActivityId", required = true) String onlineActivityId,
			@RequestParam(value = "openId", required = true) String openId,
			Model model,
			@RequestParam(value = "token", required = true) String token,
			@RequestParam(value = "cardNo", required = true) String cardNo,
			HttpServletRequest httpRequest) {

		boolean isrepeat = Utils.isRepeatSubmit(httpRequest, token);
		if (isrepeat) {
			return "1";
		}
		if (verificationCode != null && !"".equals(verificationCode)) {
			// 验证手机短信验证�?
			DxChartMemberValidateInput dxInput = new DxChartMemberValidateInput();
			dxInput.setLoginName(phoneNumber);
			dxInput.setCaptcha(verificationCode);

			DxChartMemberValidateOutput dxOuptut = (DxChartMemberValidateOutput) wizarposUserOpenRestClient
					.post(dxInput, "/v1_0/client/user/validCaptcha",
							DxChartMemberValidateOutput.class);

			if (dxOuptut != null) {

				if ("1".equals(dxOuptut.getCode())) {
					// 请求失败
					return "2";

				} else if ("3".equals(dxOuptut.getCode())) {
					// 验证码错�?
					return "3";
				}
			} else {

				return "2";
			}
		}
		// 调用开放平台接口完成绑定券操作
		SendCouponsInput sendCouponsIn = new SendCouponsInput();
		sendCouponsIn.setMid(mid);
		sendCouponsIn.setCardNo(cardNo);
		sendCouponsIn.setMobileNo(phoneNumber);
		sendCouponsIn.setOpenId(openId);

		Map<String, String> map = new HashMap<String, String>();

		map.put("ticketId", ticketId);
		map.put("ticketNum", "1");

		List<Map<String, String>> ticketIds = new ArrayList<Map<String, String>>();

		ticketIds.add(map);

		sendCouponsIn.setTicketIds(ticketIds);

		SendCouponsOutput sendCouponsOuptut = (SendCouponsOutput) wizarposOpenRestClient
				.post(sendCouponsIn, "/wechart/ticket/addToMember",
						SendCouponsOutput.class);

		if (sendCouponsOuptut != null) {

			if ("1".equals(sendCouponsOuptut.getCode())) {
				// 未注�?
				return "1";

			} else if ("2".equals(sendCouponsOuptut.getCode())) {
				// 验证码错�?
				return "2";
			} else if ("0".equals(sendCouponsOuptut.getCode())) {
				// 验证正确

			}
		}

		// 减少券操�?
		// 获取对应的券信息
		MyShake myShake = myShakeService.getMyShakeByid(ticketId, mid,
				onlineActivityId);

		myShake.setTicketNum(myShake.getTicketNum() - 1);

		myShakeService.update(myShake);

		// 更新领取人的活动历时记录
		MyOnlineActivityHistory myOnlineActivityHistory = myOnlineActivityHistoryService
				.getMyOnlineActivityHistoryByOpenId(openId,
						myShake.getOnlineActivityId());

		myOnlineActivityHistory.setMobileNo(phoneNumber);

		myOnlineActivityHistoryService.save(myOnlineActivityHistory);

		// 调用运维平台接口完成绑定会员操作
		// 会员同步
		MemberSyncInput memberSyncInput = new MemberSyncInput();
		memberSyncInput.setCardNo(cardNo);
		memberSyncInput.setMid(mid);

		memberSyncInput.setMobileNo(phoneNumber);
		memberSyncInput.setOpenId(openId);

		MemberSyncOutput memberSyncOutput = (MemberSyncOutput) wizarposUserOpenRestClient
				.post(memberSyncInput, "/v1_0/client/usermember/memberSync",
						MemberSyncOutput.class);

		if (memberSyncOutput != null) {

			if ("1".equals(memberSyncOutput.getCode())) {
				// 未注�?
				return "3";

			} else if ("2".equals(memberSyncOutput.getCode())) {
				// 验证码错�?
				return "2";
			} else if ("0".equals(memberSyncOutput.getCode())) {
				// 验证正确 绑定对应的券及注册会�?

			}
		}

		return "0";
	}

	/**
	 * 摇券 二维码版
	 * 
	 * @param mid
	 *            东志信的慧商户号
	 * @param openId
	 *            东志信公众号用户的openid
	 * @return
	 */
	@RequestMapping(value = "/qr_shake")
	public ModelAndView qrShake(
			@RequestParam(value = "mid", required = true) String mid,
			@RequestParam(value = "openId", required = true) String openId,
			Model model) {

		MyOnlineActivity myOnlineActivity = myOnlineActivityService
				.getMyOnlineActivityByMid(mid);
		if (myOnlineActivity == null) { // 没有开启活动
			model.addAttribute("count", 0);
			return new ModelAndView("onlineActivity/yaoyiyao2");
		}

		MyOnlineActivityHistory myOnlineActivityHistory = myOnlineActivityHistoryService
				.getMyOnlineActivityHistoryByOpenId(openId,
						myOnlineActivity.getId());

		if (myOnlineActivityHistory == null) {

			myOnlineActivityHistory = new MyOnlineActivityHistory();

			myOnlineActivityHistory.setMid(mid);
			myOnlineActivityHistory.setOnlineActivityId(myOnlineActivity
					.getId());
			myOnlineActivityHistory.setOpenId(openId);
			myOnlineActivityHistory.setHaveReceivedNum(0l);
			myOnlineActivityHistoryService.save(myOnlineActivityHistory);
		}

		return new ModelAndView("onlineActivity/yaoyiyao2")
				.addObject("mid", mid)
				.addObject("openId", openId)
				.addObject(
						"count",
						myOnlineActivity.getMaxNum()
								- myOnlineActivityHistory.getHaveReceivedNum());
	}

	/**
	 * 二维码版本摇一摇页面功能支持
	 * 
	 * @param mid
	 *            东志信mid
	 * @param openId
	 *            东志信公众号用户openid
	 * @param model
	 * @param httpRequest
	 * @return
	 */
	@RequestMapping(value = "/h5shakeQr", method = RequestMethod.POST)
	public @ResponseBody String h5shakeQr(
			@RequestParam(value = "mid", required = true) String mid,
			@RequestParam(value = "openId", required = true) String openId,
			Model model, HttpServletRequest httpRequest) {

		JSONObject obj = new JSONObject();
		Utils.setSessionToken(httpRequest);
		// 获取此商户开启的线上活动, 一个商户只能开启一次?
		MyOnlineActivity myOnlineActivity = myOnlineActivityService
				.getMyOnlineActivityByMid(mid);
		// 剩余可以摇的次数
		Long count = 0l;
		if (myOnlineActivity != null) {
			// 查询活动流水看是否已经领取满
			MyOnlineActivityHistory myOnlineActivityHistory = myOnlineActivityHistoryService
					.getMyOnlineActivityHistoryByOpenId(openId,
							myOnlineActivity.getId());

			if (myOnlineActivityHistory == null) {
				myOnlineActivityHistory = new MyOnlineActivityHistory();
				myOnlineActivityHistory.setMid(mid);
				myOnlineActivityHistory.setOnlineActivityId(myOnlineActivity
						.getId());
				myOnlineActivityHistory.setOpenId(openId);
				myOnlineActivityHistory.setHaveReceivedNum(1l);
				myOnlineActivityHistoryService.save(myOnlineActivityHistory);
				count = myOnlineActivity.getMaxNum() - 1l;
			} else {
				// 判断当前的微信账户是否已经领取完它对应的份额
				Long haveReceivedNum = myOnlineActivityHistory
						.getHaveReceivedNum();
				// 活动允许次数
				Long maxNum = myOnlineActivity.getMaxNum();
				if (maxNum <= haveReceivedNum) {
					// 领取次数已用完
					obj.put("code", "-1");
					return obj.toString();
				} else {
					long received = myOnlineActivityHistory
							.getHaveReceivedNum() + 1;
					myOnlineActivityHistory.setHaveReceivedNum(received);
					myOnlineActivityHistoryService
							.save(myOnlineActivityHistory);
					count = myOnlineActivity.getMaxNum() - received;
				}
			}
		} else {
			obj.put("count", count);
			obj.put("code", "-3");
			return obj.toString();
		}

		// 剩余次数
		obj.put("count", count);

		// 活动ID
		String onlineActivityId = myOnlineActivity.getId();
		// 查询开放平台是否已经注册慧银会员
		// RegisteredMemberQueryInput input = new RegisteredMemberQueryInput();
		// input.setMid(mid);
		// input.setOpenId(openId);
		// RegisteredMemberQueryOutput ouptut = (RegisteredMemberQueryOutput)
		// wizarposOpenRestClient
		// .post(input, "/wechart/registerMember",
		// RegisteredMemberQueryOutput.class);
		// String cardNo = null;
		// String mobileNo = null;
		// // 判断是否为慧银注册会员
		// if (SUCCESS.equals(ouptut.getCode()))
		// {
		// if (ouptut.getResult() != null
		// && ouptut.getResult().getCardNo() != null)
		// {
		// // 是慧银注册会员
		// cardNo = ouptut.getResult().getCardNo();
		// if (ouptut.getResult().getMobileNo() != null
		// && !"".equals(ouptut.getResult().getMobileNo()))
		// {
		// mobileNo = ouptut.getResult().getMobileNo();
		// }
		// }
		// } else if (EXIST.equals(ouptut.getCode()))
		// {
		// // 是慧银注册会员
		// cardNo = ouptut.getResult().getCardNo();
		// if (ouptut.getResult().getMobileNo() != null
		// && !"".equals(ouptut.getResult().getMobileNo()))
		// {
		// }
		// }

		// 线上摇券获取券逻辑
		String ticketDefId = null;
		// --------------------------------------------红包逻辑---------------------------------------------------开始
		// 获取当前摇奖的openId是否已经领取对应的现金红包记录，当前红包限制每人每次活动限领一次
		// MyOnlineActivityDetail
		// myOnlineActivityDetail=myOnlineActivityDetailService.getMyOnlineActivityDetail(mid,
		// myOnlineActivity.getId(), openId);
		// 如果不存在对应的领奖记录，则可以进入领奖流程
		List<MyShake> myShakeList = null;
		// 因为这里传递过来的都是东志信对应的公众号的openId

		// 获取所有已经领取的券发行mid
		List<String> ticketMids = myOnlineActivityDetailService
				.getMyOnlineActivityDetailTicketMidList(openId,
						onlineActivityId);

		// 获取开启活动的所有优惠券
		myShakeList = myShakeService.getMyShakeList(mid, onlineActivityId,
				ticketMids);

		if (myShakeList == null) {
			//
			obj.put("code", "-4");
			return obj.toString();
		}

		initData(myShakeList);

		Integer weightSum = 0;
		for (WeightCategory wc : categorys) {
			weightSum += wc.getWeight();
		}

		if (weightSum <= 0) {
			// 活动已结束
			obj.put("code", "-2");
			return obj.toString();
		}

		Integer n = random.nextInt(weightSum); // n in [0, weightSum)
		Integer m = 0;
		for (WeightCategory wc : categorys) {
			if (m <= n && n < m + wc.getWeight()) {
				ticketDefId = wc.getCategory();
				break;
			}
			m += wc.getWeight();
		}

		if (StringUtils.isEmpty(ticketDefId)) {
			obj.put("code", "-4");
			return obj.toString();
		}

		// 获取对应的券信息
		MyShake myShake = null;
		for (MyShake item : myShakeList) {
			if (ticketDefId.equals(item.getTicketId())) {
				myShake = item;
				break;
			}
		}

		if ("10".equals(myShake.getTicketType())) {
			// 类型10为空券
			obj.put("type", 10);
		} else if ("9".equals(myShake.getTicketType())) {
			// 类型9为红包 TODO
			obj.put("type", 9);

			MrtWechartUserInfoInput userInfoInput = new MrtWechartUserInfoInput();
			userInfoInput.setMid(mid);
			userInfoInput.setOpenId(openId);
			MrtWechartUserInfoOutput userInfoOutput = (MrtWechartUserInfoOutput) wizarposOpenRestClient
					.post(userInfoInput, "/wxshop/userinfo",
							MrtWechartUserInfoOutput.class);
			MrtWechartUserInfo userInfo = null;
			if (userInfoOutput == null
					|| SysConstants.OPEN_ERROR.equals(userInfoOutput.getCode())) {
				obj.put("code", "0");
				obj.put("type", 10);
				return obj.toString();
			} else if (SysConstants.NO_MERCHANT_CODE.equals(userInfoOutput
					.getCode())) {
				obj.put("code", "-4");
				return obj.toString();
			} else {
				userInfo = userInfoOutput.getResult();
			}

			if (userInfo == null || "0".equals(userInfo.getSubscribe())) {
				// 未关注或已取消关注 出关注二维码
				String qrTicket = getQrHongbao(mid, myShake.getId(),
						onlineActivityId);
				if (qrTicket == null) {
					obj.put("code", "0");
					obj.put("type", 10);
					return obj.toString();
				} else {
					obj.put("qrTicket", qrTicket);
				}
			} else {
				// 获取要发放的红包
				MyRedEnvelopes red = myRedEnvelopesService.getMyRedEnvelopes(
						mid, onlineActivityId);

				// 请求开放平台发放红包
				DzxWxHongbaoSendInput inputSendHongbao = new DzxWxHongbaoSendInput();
				inputSendHongbao.setMid(mid);
				inputSendHongbao.setOpenid(openId);
				inputSendHongbao.setActName(myOnlineActivity.getActivityName());
				inputSendHongbao.setAmount(String.valueOf(red.getAmount()));
				CommonResultOutput output = (CommonResultOutput) wizarposOpenRestClient
						.post(inputSendHongbao, "/weixin/dzxSendWxHongbao",
								CommonResultOutput.class);

				// 发放成功，保存发放记录
				if (output != null && "0".equals(output.getCode())) {
					MyOnlineActivityDetail myOnlineActivityDetail = new MyOnlineActivityDetail();
					myOnlineActivityDetail.setAmount(red.getAmount());
					myOnlineActivityDetail
							.setOnlineActivityId(onlineActivityId);
					myOnlineActivityDetail.setPersonOpenId(openId);
					myOnlineActivityDetail.setReceiveTime(new Date());
					myOnlineActivityDetail.setTicketMid(myShake.getTicketMid());
					myOnlineActivityDetail.setTicketType(myShake
							.getTicketType());
					myOnlineActivityDetail.setTicketContent(myShake
							.getTicketContent());
					myOnlineActivityDetailService
							.saveMyOnlineActivityDetail(myOnlineActivityDetail);
					myRedEnvelopesService.delete(red);
				}
			}

		} else {
			// 查询卡券定义信息，获取券所属商户mid
			TicketDefInfoInput ticketDefInfoInput = new TicketDefInfoInput();
			ticketDefInfoInput.setTicketDefIds(Arrays.asList(ticketDefId));
			TicketDefInfoOutput ticketDefInfoOutput = (TicketDefInfoOutput) wizarposOpenRestClient
					.post(ticketDefInfoInput, "/wechart/ticketdef/info",
							TicketDefInfoOutput.class);
			MrtTicketDef ticketDef = null;
			if (ticketDefInfoOutput == null
					|| SysConstants.OPEN_ERROR.equals(ticketDefInfoOutput
							.getCode())) {
				log.error("获取券信息请求开放平台失败");
				obj.put("code", "10");
				return obj.toString();
			} else {
				ticketDef = ticketDefInfoOutput.getResult().get(0);
			}
			if (ticketDef == null || "0".equals(ticketDef.getUsedFlag())
					|| "1".equals(ticketDef.getState())) {// 卡券已经停用或逻辑删除
				log.error("卡券信息异常");
				obj.put("code", "10");
				return obj.toString();
			}

			String childMid = ticketDef.getMid();

			// 商户信息
			MrtMerchantDef mrt = mrtMerchantDefService
					.getSysMerchantDefByMid(childMid);
			if (mrt == null) {
				log.error("子商户信息异常");
				obj.put("code", "10");
				return obj.toString();
			}

			// 商户公众号内用户信息
			MyOpenidRelation relation = myOpenidRelationService
					.getByMidAndDzxOpenid(childMid, openId);

			if (relation == null || relation.getStatus() != 0) {
				// 没有绑定关系，出关注二维码
				Object qrTicket = null;
				try {
					qrTicket = getQrTicket(mid, childMid, ticketDefId, openId,
							onlineActivityId);
				} catch (Exception e) {
					log.error("创建二维码异常");
					obj.put("code", "0");
					obj.put("type", 10);
					return obj.toString();
				}

				if (qrTicket == null) {
					log.error("创建二维码异常");
					obj.put("code", "0");
					obj.put("type", 10);
					return obj.toString();
				} else {
					obj.put("qrTicket", qrTicket);
				}

			} else {
				String gzhOpenid = relation.getGzhOpenid();

				MrtWechartUserInfoInput userInfoInput = new MrtWechartUserInfoInput();
				userInfoInput.setMid(childMid);
				userInfoInput.setOpenId(gzhOpenid);
				MrtWechartUserInfoOutput userInfoOutput = (MrtWechartUserInfoOutput) wizarposOpenRestClient
						.post(userInfoInput, "/wxshop/userinfo",
								MrtWechartUserInfoOutput.class);
				MrtWechartUserInfo userInfo = null;
				if (userInfoOutput == null
						|| SysConstants.OPEN_ERROR.equals(userInfoOutput
								.getCode())) {
					log.error("获取用户信息请求开放平台失败");
					obj.put("code", "0");
					obj.put("type", 10);
					return obj.toString();
				} else if (SysConstants.NO_MERCHANT_CODE.equals(userInfoOutput
						.getCode())) {
					log.error("子商户信息异常");
					obj.put("code", "0");
					obj.put("type", 10);
					return obj.toString();
				} else {
					userInfo = userInfoOutput.getResult();
				}

				if ("0".equals(userInfo.getSubscribe())) {
					// 已取消关注 出关注二维码
					Object qrTicket = null;
					try {
						qrTicket = getQrTicket(mid, childMid, ticketDefId,
								openId, onlineActivityId);
					} catch (Exception e) {
						log.error("创建二维码异常");
						obj.put("code", "0");
						obj.put("type", 10);
						return obj.toString();
					}

					if (qrTicket == null) {
						log.error("创建二维码异常");
						obj.put("type", 10);
						return obj.toString();
					} else {
						obj.put("qrTicket", qrTicket);
					}
				} else {
					// 查询开放平台是否已经注册慧银会员
					RegisteredMemberQueryInput memberInput = new RegisteredMemberQueryInput();
					memberInput.setMid(childMid);
					memberInput.setOpenId(gzhOpenid);
					RegisteredMemberQueryOutput memberOuptut = (RegisteredMemberQueryOutput) wizarposOpenRestClient
							.post(memberInput, "/wechart/registerMember",
									RegisteredMemberQueryOutput.class);
					String gzhCardNo = null;
					// 判断是否为慧银注册会员 不是的话快速注

					if (SUCCESS.equals(memberOuptut.getCode())) {
						if (memberOuptut.getResult() != null
								&& memberOuptut.getResult().getCardNo() != null) {
							// 快速注册的会员
							gzhCardNo = memberOuptut.getResult().getCardNo();
						}
					} else if (EXIST.equals(memberOuptut.getCode())) {
						// 是慧银注册会员
						gzhCardNo = memberOuptut.getResult().getCardNo();
					}

					log.debug(memberOuptut.getCode());
					log.debug(gzhCardNo);

					obj.put("childMid", childMid);
					obj.put("gzhOpenid", gzhOpenid);
					obj.put("gzhCardNo", gzhCardNo);
				}
			}

			// 券信息
			obj.put("ticketDefId", ticketDefId);
			obj.put("ticketName", ticketDef.getTicketName());
			obj.put("ticketDesc", ticketDef.getDescription());
			// 商户信息
			obj.put("mrtName", mrt.getMerchantName());
			obj.put("mrtDesc", mrt.getMerchantSummary());
			obj.put("mrtAddr", mrt.getMerchantAddr());
		}

		String server_token = (String) httpRequest.getSession().getAttribute(
				SysConstants.SESSION_TOKEN);

		obj.put("code", "0");
		obj.put("count", count);

		obj.put("onlineActivityId", myOnlineActivity.getId());
		obj.put("token", server_token);

		return obj.toString();
	}

	/**
	 * 获取摇到的券
	 * 
	 * @param mid
	 * @param ticketId
	 * @param onlineActivityId
	 * @param openId
	 * @param token
	 * @param cardNo
	 * @param childMid
	 * @param gzhOpenid
	 * @param model
	 * @param httpRequest
	 * @return
	 */
	@RequestMapping(value = "/receiveShake")
	public @ResponseBody String receiveShake(
			@RequestParam(value = "mid", required = true) String mid,
			@RequestParam(value = "ticketId", required = true) String ticketId,
			@RequestParam(value = "onlineActivityId", required = true) String onlineActivityId,
			@RequestParam(value = "openId", required = true) String openId,
			@RequestParam(value = "token", required = true) String token,
			@RequestParam(value = "gzhCardNo", required = true) String gzhCardNo,
			@RequestParam(value = "childMid", required = true) String childMid,
			@RequestParam(value = "gzhOpenid", required = true) String gzhOpenid,
			Model model, HttpServletRequest httpRequest) {

		// 检查本次摇去凭证，是否重复领取
		boolean isrepeat = Utils.isRepeatSubmit(httpRequest, token);
		if (isrepeat) {
			return "1";
		}

		// 获取对应的券信息
		MyShake myShake = myShakeService.getMyShakeByid(ticketId, mid,
				onlineActivityId);

		// 已经领取完了
		if (myShake.getTicketNum() <= 0) {
			return "2";
		}

		// 调用开放平台接口完成绑定券操作
		Map<String, String> map = new HashMap<String, String>();
		map.put("ticketId", ticketId);
		map.put("ticketNum", "1");

		List<Map<String, String>> ticketIds = new ArrayList<Map<String, String>>();
		ticketIds.add(map);

		SendCouponsInput sendCouponsIn = new SendCouponsInput();
		sendCouponsIn.setMid(childMid);
		sendCouponsIn.setOpenId(gzhOpenid);
		sendCouponsIn.setTicketIds(ticketIds);
		sendCouponsIn.setCardNo(gzhCardNo);

		log.debug(childMid);
		log.debug(gzhOpenid);
		log.debug(ticketIds);
		log.debug(gzhCardNo);

		SendCouponsOutput sendCouponsOuptut = (SendCouponsOutput) wizarposOpenRestClient
				.post(sendCouponsIn, "/wechart/ticket/addToMember",
						SendCouponsOutput.class);

		if (sendCouponsOuptut != null) {
			log.debug(sendCouponsOuptut.getCode());
			if (!"0".equals(sendCouponsOuptut.getCode())) {
				// 错误
				return sendCouponsOuptut.getCode();
			}
		}

		// 减少券操作
		myShake.setTicketNum(myShake.getTicketNum() - 1);
		myShakeService.update(myShake);

		// 更新领取人的活动历时记录
		MyOnlineActivityHistory myOnlineActivityHistory = myOnlineActivityHistoryService
				.getMyOnlineActivityHistoryByOpenId(openId,
						myShake.getOnlineActivityId());
		myOnlineActivityHistory.setGzhOpenid(gzhOpenid);
		myOnlineActivityHistoryService.save(myOnlineActivityHistory);

		MyOnlineActivityDetail myOnlineActivityDetail = new MyOnlineActivityDetail();
		myOnlineActivityDetail.setOnlineActivityId(onlineActivityId);
		myOnlineActivityDetail.setPersonOpenId(openId);
		myOnlineActivityDetail.setReceiveTime(new Date());
		myOnlineActivityDetail.setTicketMid(myShake.getTicketMid());
		myOnlineActivityDetail.setTicketType(myShake.getTicketType());
		myOnlineActivityDetail.setTicketContent(myShake.getTicketContent());
		myOnlineActivityDetailService
				.saveMyOnlineActivityDetail(myOnlineActivityDetail);

		// 领取后删除本次摇的凭证
		Utils.removeSessionToken(httpRequest);

		return "0";
	}

	/**
	 * 创建微信卡券二维码ticket,并保存数据到数据库
	 * 
	 * @param mid
	 *            东志信mid
	 * @param gzhMid
	 *            商户mid
	 * @param ticketDefId
	 *            活动送的商户券
	 * @param dzxOpenid
	 *            东志信公众号用户openid
	 * @return
	 * @throws Exception
	 */
	public Object getQrTicket(String mid, String gzhMid, String ticketDefId,
			String dzxOpenid, String onlineActivityId) throws Exception {
		DzxShekeQrInput tokenInput = new DzxShekeQrInput();

		JSONObject obj = new JSONObject();

		obj.put("ticketDefId", ticketDefId);
		obj.put("onlineActivityId", onlineActivityId);
		obj.put("mid", mid);
		obj.put("ticketMId", gzhMid);

		tokenInput.setInfo(obj.toJSONString()); // 关注后送的券
		tokenInput.setSubInfo(dzxOpenid); // 绑定的东志信openid
		tokenInput.setMid(gzhMid); // 商户mid

		CommonResultOutput output = (CommonResultOutput) wizarposOpenRestClient
				.post(tokenInput, "/weixin/dzxShekeQr",
						CommonResultOutput.class);

		if (output == null
				|| !SysConstants.OPEN_SUCCESS.equals(output.getCode())) {
			log.error("system error");
			return null;
		}

		Object ticket = output.getResult();

		return ticket;
	}

	/**
	 * 创建微信红包二维码ticket,并保存数据到数据库
	 * 
	 * @param mid
	 * @param shakeId
	 * @param activeId
	 * @return
	 */
	public String getQrHongbao(String mid, String shakeId, String activeId) {
		AccessTokenInput jsInput = new AccessTokenInput();
		jsInput.setMid(mid);
		AccessTokenOutput jsOutput = (AccessTokenOutput) wizarposOpenRestClient
				.post(jsInput, "/weixin/accesstoken", AccessTokenOutput.class);
		String accessToken = null;
		if (jsOutput == null
				|| SysConstants.OPEN_ERROR.equals(jsOutput.getCode())) {
			log.error("system error, open call error");
			return null;
		} else if (SysConstants.NO_MERCHANT_CODE.equals(jsOutput.getCode())) {
			log.error("merchant missing:" + mid);
			return null;
		} else {
			Result apiTicket = jsOutput.getResult();
			if (apiTicket == null) {
				log.error("system error, apiTicket is null");
				return null;
			}
			accessToken = apiTicket.getToken();
		}

		// 创建二维码ticket的URL
		String qrcodeUrl = SysConstants.QRCODE_URL.replace(
				SysConstants.ACCESS_TOKEN, accessToken);

		// 东志信关注送券零时二维码，场景值固定为2，有效期1小时
		JSONObject scene = new JSONObject();
		scene.put("scene_id", 3);

		JSONObject action_info = new JSONObject();
		action_info.put("scene", scene);

		JSONObject param = new JSONObject();
		param.put("expire_seconds", 3600);
		param.put("action_name", "QR_SCENE");
		param.put("action_info", action_info);

		JSONObject response = null;
		try {
			response = wposHttpClient.post(qrcodeUrl, param);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}

		if (response.containsKey("errcode")) {
			System.out.println(response.getString("errmsg"));
			return null;
		}

		String ticket = response.getString("ticket");
		try {
			ticket = URLEncoder.encode(ticket, "utf-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			return null;
		}
		long expireSeconds = response.getLongValue("expire_seconds");
		Long expiryTime = System.currentTimeMillis() + 1000 * expireSeconds;

		// 获取传入参数，写入对应的token表
		SysInToken sysInToken = new SysInToken();
		sysInToken.setTokenId(ticket);
		sysInToken.setMid(mid);
		sysInToken.setInfo(shakeId);
		sysInToken.setSubInfo(activeId);
		sysInToken.setExpiryTime(expiryTime);

		try {
			sysInTokenService.save(sysInToken);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}

		return ticket;
	}

	@RequestMapping(value = "/test")
	@ResponseBody
	public void test(HttpServletRequest httpRequest) {
		// 请求微信 js api的完整页面地址
		String url = httpRequest.getScheme() + "://"; // 请求协议 http 或 https
		url += httpRequest.getHeader("host"); // 请求服务器
		url += httpRequest.getRequestURI(); // 工程名
		if (httpRequest.getQueryString() != null) { // 判断请求参数是否为空
			url += "?" + httpRequest.getQueryString(); // 参数
		}
		log.info(url);

		url = httpRequest.getScheme() + "://"; // 请求协议 http 或 https
		url += httpRequest.getServerName(); // 请求服务器
		url += httpRequest.getRequestURI(); // 工程名
		if (httpRequest.getQueryString() != null) { // 判断请求参数是否为空
			url += "?" + httpRequest.getQueryString(); // 参数
		}
		log.info(url);
	}

}
